package com.dog.basics.service.common.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dog.basics.bean.model.common.DogUserConnect;
import com.dog.basics.bean.model.mtkj.MtDeviceOrder;
import com.dog.basics.bean.model.mtkj.MtOrder;
import com.dog.basics.bean.vo.api.mtkj.ApiOrderPrepayVo;
import com.dog.basics.common.util.HttpContextUtils;
import com.dog.basics.common.util.IpKit;
import com.dog.basics.common.util.R;
import com.dog.basics.common.util.serialNumberUtils;
import com.dog.basics.dao.common.DogUserConnectMapper;
import com.dog.basics.dao.mtkj.MtDeviceOrderMapper;
import com.dog.basics.dao.mtkj.MtOrderMapper;
import com.dog.basics.security.util.SecurityUtils;
import com.dog.basics.service.common.WeChatMiniService;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @program: clumsy_security
 * @description: 微信业务实现
 * @author: Guo
 * @create: 2019-05-09 15:54
 **/
@Log4j2
@Service
@AllArgsConstructor
public class WeChatMiniServiceImpl implements WeChatMiniService {
    private final DogUserConnectMapper dogUserConnectMapper;
    private final MtDeviceOrderMapper mtDeviceOrderMapper;
    private final MtOrderMapper mtOrderMapper;
    @Qualifier("wxMiniPayService")
    private final WxPayService wxMiniPayService;  //微信支付
    private final WxMaService wxMaService;

    /**
     * 微信调用预支付
     *
     * @param orderPrepayVo
     * @return
     */
    @Override
    public R callOrderPrepayment(ApiOrderPrepayVo orderPrepayVo) {
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        try {
            Map<String, Object> payInfo = CollUtil.newHashMap();
            request.setOutTradeNo(orderPrepayVo.getOrderNo()); //商户订单
            request.setTotalFee(orderPrepayVo.getHnrbMoney().multiply(BigDecimal.valueOf(100)).intValue()); //金额
            request.setSpbillCreateIp(IpKit.getRealIp(HttpContextUtils.getHttpServletRequest())); //IP
            request.setBody(orderPrepayVo.getProName()); //描述
            request.setOpenid(orderPrepayVo.getOpenid());
            request.setTradeType("JSAPI");  //H5 调用值
            request.setSignType("MD5"); //默认MD5加密
            request.setProductId(orderPrepayVo.getOrderId()+"");

            if (Validator.equal(orderPrepayVo.getOrderType(), 0)) {
                // 设备订单
                request.setNotifyUrl(StrUtil.format("{}/api/device/order/wxPay/minicallbackOrder", wxMiniPayService.getConfig().getNotifyUrl()));
            } else if (Validator.equal(orderPrepayVo.getOrderType(), 1)) {
                // 押金订单
                request.setNotifyUrl(StrUtil.format("{}/api/device/deposit/wxPay/minicallbackOrder", wxMiniPayService.getConfig().getNotifyUrl()));
            } else {
                request.setAppid("wx3cdd3a69078298d1");
                request.setNotifyUrl(StrUtil.format("{}/api/order/wxPay/minicallbackOrder", wxMiniPayService.getConfig().getNotifyUrl()));
            }
            WxPayMpOrderResult wxPayMpOrderResult = this.wxMiniPayService.createOrder(request);
            payInfo.put("rows", wxPayMpOrderResult);
            payInfo.put("orderNo", orderPrepayVo.getOrderNo());
            payInfo.put("orderId", orderPrepayVo.getOrderId());
            return R.ok(payInfo);
        } catch (Exception e) {
            Validator.validateTrue(Boolean.FALSE, "调用微信预支付出错，订单号:" + orderPrepayVo.getOrderNo());
        }
        return R.failed("支付出错,联系管理员");
    }


    /**
     * 解析回调数据
     *
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @Override
    public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) throws WxPayException {
        if (ObjectUtils.isNull(xmlData)) {
            return null;
        }
        return this.wxMiniPayService.parseOrderNotifyResult(xmlData);
    }

    /**
     * 重新支付
     *
     * @param orderId
     * @return
     */
    @Override
    @SneakyThrows
    public R rePayOrder(Long orderId) {
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        MtDeviceOrder mtDeviceOrder = mtDeviceOrderMapper.selectById(orderId);
        Validator.validateNotNull(mtDeviceOrder, "暂无数据!");
        //支付编号
        String payOrderNo = serialNumberUtils.serialNumberGenerate().toString();
        mtDeviceOrder.setOrderMainNo(payOrderNo);
        mtDeviceOrder.setUpdateTime(DateUtil.currentSeconds());
       Validator.validateTrue(mtDeviceOrderMapper.updateById(mtDeviceOrder)>0,"修改失败") ;

        try {
            List<DogUserConnect> list = dogUserConnectMapper.selectList(Wrappers.<DogUserConnect>lambdaQuery().eq(DogUserConnect::getUserId, SecurityUtils.getUser().getUserId()));
            Validator.validateTrue(CollUtil.isNotEmpty(list), "用户未绑定微信不能付款");
            DogUserConnect dogUserConnect = list.get(0);
            request.setOutTradeNo(payOrderNo); //商户订单
            request.setTotalFee(mtDeviceOrder.getOrderPayMoney().multiply(BigDecimal.valueOf(100)).intValue()); //金额
            request.setSpbillCreateIp(IpKit.getRealIp(HttpContextUtils.getHttpServletRequest())); //IP
            request.setOpenid(dogUserConnect.getMiniOpenid());
            request.setBody("无");
            request.setTradeType("JSAPI");  //H5 调用值
            request.setSignType("MD5"); //默认MD5加密
            request.setProductId(orderId + "");
            Map<String, String> payInfo = this.wxMiniPayService.createOrder(request);
            return R.ok(payInfo);
        } catch (Exception e) {
            Validator.validateTrue(Boolean.FALSE, "调用微信预支付出错，订单号:" + mtDeviceOrder.getOrderNo());
        }
        return R.failed("支付出错,联系管理员");
    }

    /**
     * 重新支付
     *
     * @param orderId
     * @return
     */
    @Override
    @SneakyThrows
    public R reShoppPayOrder(Long orderId) {
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        MtOrder mtOrder = mtOrderMapper.selectById(orderId);
        Validator.validateNotNull(mtOrder, "暂无数据!");
        //支付编号
        String payOrderNo = serialNumberUtils.serialNumberGenerate().toString();
        mtOrder.setOutTradeNo(payOrderNo);
        mtOrder.setPayTime(DateUtil.currentSeconds());
        mtOrderMapper.updateById(mtOrder);

        try {
            Map<String, Object> payInfo = CollUtil.newHashMap();
            List<DogUserConnect> list = dogUserConnectMapper.selectList(Wrappers.<DogUserConnect>lambdaQuery().eq(DogUserConnect::getUserId, SecurityUtils.getUser().getUserId()));
            Validator.validateTrue(CollUtil.isNotEmpty(list), "用户未绑定微信不能付款");
            DogUserConnect dogUserConnect = list.get(0);
            request.setOutTradeNo(payOrderNo); //商户订单
            request.setTotalFee(mtOrder.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue()); //金额
            request.setSpbillCreateIp(IpKit.getRealIp(HttpContextUtils.getHttpServletRequest())); //IP
            request.setOpenid(dogUserConnect.getMiniShopOpenid());
            request.setBody("重新支付");
            request.setTradeType("JSAPI");  //H5 调用值
            request.setSignType("MD5"); //默认MD5加密
            request.setAppid("wx3cdd3a69078298d1");
            request.setProductId(payOrderNo);
            request.setNotifyUrl(StrUtil.format("{}/api/order/wxPay/minicallbackOrder", wxMiniPayService.getConfig().getNotifyUrl()));
            WxPayMpOrderResult wxPayMpOrderResult = this.wxMiniPayService.createOrder(request);
            payInfo.put("rows", wxPayMpOrderResult);
            payInfo.put("orderNo", mtOrder.getOutTradeNo());
            return R.ok(payInfo);

        } catch (Exception e) {
            Validator.validateTrue(Boolean.FALSE, "调用微信预支付出错，订单号:" + mtOrder.getOrderNo());
        }
        return R.failed("支付出错,联系管理员");
    }

    /**
     * 申请退款
     *
     * @param request
     * @return guonh 2019年10月14日
     */
    @Override
    @SneakyThrows
    public WxPayRefundResult refund(WxPayRefundRequest request) {
        return this.wxMiniPayService.refund(request);
    }

    /**
     * 企业付款到零钱
     *
     * @param request
     * @return guonh 2019年10月21日
     */
    @Override
    @SneakyThrows
    public EntPayResult wxEntPay(EntPayRequest request) {
        return this.wxMiniPayService.getEntPayService().entPay(request);
    }

    /**
     * 推送订阅消息
     *
     * @return
     */
    @Override
    public Boolean pushMsg(String openId, String keyword1, String keyword2) {
        //2,设置模版信息（keyword1：类型，keyword2：内容）
        List<WxMaSubscribeMessage.Data> templateDataList = new ArrayList<>(2);
        WxMaSubscribeMessage.Data data1 = new WxMaSubscribeMessage.Data("time2", keyword1);
        WxMaSubscribeMessage.Data data2 = new WxMaSubscribeMessage.Data("time3", keyword2);
        templateDataList.add(data1);
        templateDataList.add(data2);
        //3，设置推送消息
        WxMaSubscribeMessage templateMessage = new WxMaSubscribeMessage();
        templateMessage.setToUser(openId);
       // templateMessage.setTemplateId("eMz_SnuIJmbHcHcWIX20VSNf7mrDov0Mmf0H7lsGSwk");
        templateMessage.setTemplateId("eMz_SnuIJmbHcHcWIX20VbEJ1_0exEL-IugSoHM5tIo");
        templateMessage.setPage("pages/homePage/index");
        templateMessage.setData(templateDataList);
     //   templateMessage.setMiniprogramState(WxMaConstants.MiniprogramState.FORMAL);
        //4，发起推送
        try {
            wxMaService.getMsgService().sendSubscribeMsg(templateMessage);
        } catch (WxErrorException e) {
            System.out.println("推送失败：" + e.getMessage());
            return Boolean.TRUE;
        }

        return Boolean.TRUE;
    }

}
